package com.wonder.common.utils;
import java.lang.management.ManagementFactory;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;
import org.apache.commons.lang3.time.DateFormatUtils;

import com.wonder.common.constants.Constants;



/**
 * 时间工具类
 * 
 * @author 
 */
public class DateUtils extends org.apache.commons.lang3.time.DateUtils
{
    public static String YYYY = "yyyy";

    public static String YYYY_MM = "yyyy-MM";

    public static String YYYY_MM_DD = "yyyy-MM-dd";

    public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

    public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
    
    private static String[] parsePatterns = {
            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", 
            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};

    /**
     * 获取当前Date型日期
     * 
     * @return Date() 当前日期
     */
    public static Date getNowDate()
    {
        return new Date();
    }


    /**
     * Two date is the same day
     */
    public static  boolean isSameDay(Date date1,Date date2){
        if(date1==null ||date2==null) return false;
        Calendar cal1 = Calendar.getInstance();
        Calendar cal2 = Calendar.getInstance();
        cal1.setTime(date1);
        cal2.setTime(date2);
        if(cal1.get(Calendar.YEAR)==cal2.get(Calendar.YEAR)
                && cal1.get(Calendar.DAY_OF_YEAR)==cal2.get(Calendar.DAY_OF_YEAR)) return true;
        return false;
    }

    /**
     * Two date is the same day
     */
    public static  boolean isSameWeek(Date date1,Date date2){
        if(date1==null ||date2==null) return false;
        Calendar cal1 = Calendar.getInstance();
        Calendar cal2 = Calendar.getInstance();
        cal1.setTime(date1);
        cal2.setTime(date2);
        int subYear = cal1.get(Calendar.YEAR)-cal2.get(Calendar.YEAR);
        //subYear==0,说明是同一年
        if(subYear == 0)
        {
            if(cal1.get(Calendar.WEEK_OF_YEAR) == cal2.get(Calendar.WEEK_OF_YEAR))
                return true;
        }
        //例子:cal1是"2005-1-1"，cal2是"2004-12-25"
        //java对"2004-12-25"处理成第52周
        // "2004-12-26"它处理成了第1周，和"2005-1-1"相同了
        //大家可以查一下自己的日历
        //处理的比较好
        //说明:java的一月用"0"标识，那么12月用"11"
        else if(subYear==1 && cal2.get(Calendar.MONTH)==11)
        {
            if(cal1.get(Calendar.WEEK_OF_YEAR) == cal2.get(Calendar.WEEK_OF_YEAR))
                return true;
        }
         //例子:cal1是"2004-12-31"，cal2是"2005-1-1"
        else if(subYear==-1 && cal1.get(Calendar.MONTH)==11)
        {
            if(cal1.get(Calendar.WEEK_OF_YEAR) == cal2.get(Calendar.WEEK_OF_YEAR))
                return true;
        }
        return false;
    }

    /**
     * Two date is the same Month
     */
    public static  boolean isSameMonth(Date date1,Date date2){
        if(date1==null ||date2==null) return false;
        Calendar cal1 = Calendar.getInstance();
        Calendar cal2 = Calendar.getInstance();
        cal1.setTime(date1);
        cal2.setTime(date2);
        if(cal1.get(Calendar.YEAR)==cal2.get(Calendar.YEAR) && cal1.get(Calendar.MONTH)==cal2.get(Calendar.MONTH)
              ) return true;
        return false;
    }

    /**
     * Two date is the same Month
     */
    public static  boolean isSameYear(Date date1,Date date2){
        if(date1==null ||date2==null) return false;
        Calendar cal1 = Calendar.getInstance();
        Calendar cal2 = Calendar.getInstance();
        cal1.setTime(date1);
        cal2.setTime(date2);
        if(cal1.get(Calendar.YEAR)==cal2.get(Calendar.YEAR)) return true;
        return false;
    }

    /**
     * 获取当前日期, 默认格式为yyyy-MM-dd
     * 
     * @return String
     */
    public static String getDate()
    {
        return dateTimeNow(YYYY_MM_DD);
    }

    public static final String getTime()
    {
        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
    }

    public static final String dateTimeNow()
    {
        return dateTimeNow(YYYYMMDDHHMMSS);
    }

    public static final String dateTimeNow(final String format)
    {
        return parseDateToStr(format, new Date());
    }

    public static final String dateTime(final Date date)
    {
        return parseDateToStr(YYYY_MM_DD, date);
    }
    
    /**
     * 获取当前日期,指定格式
     * 描述:<描述函数实现的功能>.
     *
     * @return
     */
    public static String nowDate() {
        return nowDate(Constants.DATE_FORMAT_NUM);
    }
    
    /**
     * 获取当前日期
     * @return
     */
    public static Date currentDate() {
    	return strToDate(nowDateTimeStr(), Constants.DATE_FORMAT_DATE);
    }
    
    public static Date addAndSubtractDays(Date dateTime/*待处理的日期*/,int n/*加减天数*/){ 

        //日期格式 
        SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd");  
        SimpleDateFormat dd=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");     

       // System.out.println(df.format(new Date(dateTime.getTime() + n * 24 * 60 * 60 * 1000L))); 
        //System.out.println(dd.format(new Date(dateTime.getTime() + n * 24 * 60 * 60 * 1000L))); 
        //注意这里一定要转换成Long类型，要不n超过25时会出现范围溢出，从而得不到想要的日期值 
        return new Date(dateTime.getTime() + n * 24 * 60 * 60 * 1000L); 
      } 
    
    public static Date addDays(int n/*加减天数*/){ 
        return new Date(currentDate().getTime() + n * 24 * 60 * 60 * 1000L); 
      } 
    
    
    /**
     * 获取当前日期,指定格式
     * 描述:<描述函数实现的功能>.
     *
     * @return
     */
    public static String nowDate(String DATE_FORMAT) {
        SimpleDateFormat dft = new SimpleDateFormat(DATE_FORMAT);
        return dft.format(new Date());
    }

    /**
     * 获取当前日期,指定格式
     * 描述:<描述函数实现的功能>.
     *
     * @return
     */
    public static String nowDateTimeStr() {
        return nowDate(Constants.DATE_FORMAT);
    }
    /**
     * 获取当前日期,指定格式
     * 描述:<描述函数实现的功能>.
     *
     * @return
     */
    public static Date nowDateTime() {
        return new Date();
    }
    
    /**
     * parse a String to Date in a specifies fromat.
     *
     * @param dateStr
     * @param DATE_FORMAT
     * @return
     * @throws ParseException
     */
    public static Date strToDate(String dateStr, String DATE_FORMAT) {
        SimpleDateFormat myFormat = new SimpleDateFormat(DATE_FORMAT);
        try {
            return myFormat.parse(dateStr);
        } catch (ParseException e) {
            return null;
        }
    }

    public static final String parseDateToStr(final String format, final Date date)
    {
        return new SimpleDateFormat(format).format(date);
    }

    public static final Date dateTime(final String format, final String ts)
    {
        try
        {
            return new SimpleDateFormat(format).parse(ts);
        }
        catch (ParseException e)
        {
            throw new RuntimeException(e);
        }
    }

    /**
     * 日期路径 即年/月/日 如2018/08/08
     */
    public static final String datePath()
    {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyy/MM/dd");
    }

    /**
     * 日期路径 即年/月/日 如20180808
     */
    public static final String dateTime()
    {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyyMMdd");
    }
    
    /**
     * 日期路径 即年/月/日 如201808
     */
    public static final String dateTimeMonth()
    {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyyMM");
    }

    /**
     * 日期型字符串转化为日期 格式
     */
    public static Date parseDate(Object str)
    {
        if (str == null)
        {
            return null;
        }
        try
        {
            return parseDate(str.toString(), parsePatterns);
        }
        catch (ParseException e)
        {
            return null;
        }
    }
    
    /**
     * 获取服务器启动时间
     */
    public static Date getServerStartDate()
    {
        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
        return new Date(time);
    }

    /**
     * 计算两个时间差
     */
    public static String getDatePoor(Date endDate, Date nowDate)
    {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - nowDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        // long sec = diff % nd % nh % nm / ns;
        return day + "天" + hour + "小时" + min + "分钟";
    }
    
    /**
     * date add Second
     *
     * @param date
     * @param num
     * @return
     */
    public static Date addSecond(Date date, int num) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.SECOND, num);
        return calendar.getTime();
    }
    
    /**
     * 获取当前时间最近的整数分钟时间
     * @return
     */
    public static Date getNearestDate() {
		Calendar cal = Calendar.getInstance();
		int sec=cal.SECOND;
		if(sec >0) cal.add(Calendar.MINUTE, 1);
		return cal.getTime();
	}
    
    /**
     * 获取当前时间最近的整数分钟时间
     * @return
     */
    public static Date getNearestDate(int timeInterval) {
		Calendar cal = Calendar.getInstance();
		int sec=cal.SECOND;
		if(sec >0) 
			{
			   cal.add(Calendar.MINUTE, 1);
			   cal.clear(Calendar.SECOND);
			   cal.clear(Calendar.MILLISECOND);
			}
		cal.add(Calendar.SECOND, timeInterval);
		return cal.getTime();
	}
    
    /**
     * 
     * @param fromDate
     * @param toDate
     * @return
     */
    public static int diffDateDay(Date fromDate, Date toDate){
    	   DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    	   String newDate = df.format(fromDate);
    	   String sqlDate1 = df.format(toDate);
    	   try {
    		   fromDate = df.parse(newDate);
    		   toDate = df.parse(sqlDate1);
    	   } catch (ParseException e) {
    	      e.printStackTrace();
    	   }
    	   Long time =  fromDate.getTime();
    	   Long time2 =  toDate.getTime();
    	   int day = (int) ((time - time2) / (24*3600*1000));
    	   return day;
    	}
    
    
    /**
     * 
     * @param fromDate
     * @param toDate
     * @return
     */
    public static int diffDateSecond(Date fromDate, Date toDate){
    	   DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    	   String newDate = df.format(fromDate);
    	   String sqlDate1 = df.format(toDate);
    	   try {
    		   fromDate = df.parse(newDate);
    		   toDate = df.parse(sqlDate1);
    	   } catch (ParseException e) {
    	      e.printStackTrace();
    	   }
    	   Long time =  fromDate.getTime();
    	   Long time2 =  toDate.getTime();
    	   int second = (int) ((time - time2) / (1000));
    	   return second;
    	}
    
    
    public static String getStartToday() {
    	Date today = new Date();
		SimpleDateFormat startDateFormatter = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
		return startDateFormatter.format(today);
    }
    
    public static String getEndToday() {
    	Date today = new Date();
    	SimpleDateFormat endDateFormatter = new SimpleDateFormat("yyyy-MM-dd 23:59:59");
		return endDateFormatter.format(today);
    }
    
	public static String getStartWeek() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.clear(Calendar.MINUTE);
		cal.clear(Calendar.SECOND);
		cal.clear(Calendar.MILLISECOND);

		cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
		SimpleDateFormat startDateFormatter = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
		return startDateFormatter.format(cal.getTime());
	}
    
	public static String getEndWeek() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.clear(Calendar.MINUTE);
		cal.clear(Calendar.SECOND);
		cal.clear(Calendar.MILLISECOND);

		cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
		cal.add(Calendar.WEEK_OF_YEAR, 1);
		cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
		SimpleDateFormat startDateFormatter = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
		return startDateFormatter.format(cal.getTime());
	}
	
	public static String getStartMonth() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.clear(Calendar.MINUTE);
		cal.clear(Calendar.SECOND);
		cal.clear(Calendar.MILLISECOND);

		cal.set(Calendar.DAY_OF_MONTH, 1);
		SimpleDateFormat startDateFormatter = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
		return startDateFormatter.format(cal.getTime());
	}
	
	public static String getEndMonth() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.clear(Calendar.MINUTE);
		cal.clear(Calendar.SECOND);
		cal.clear(Calendar.MILLISECOND);

		cal.set(Calendar.DAY_OF_MONTH, 1);
		cal.add(Calendar.MONTH, 1);
		SimpleDateFormat startDateFormatter = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
		return startDateFormatter.format(cal.getTime());
	}
	
	 /**
     * convert long to date
     *
     * @param dateLong
     * @return
     */
    public static Date longToDate(long dateLong) {
        return new Date(dateLong);
    }

    /**
     * convert long to date string
     *
     * @param dateLong
     * @param DATE_FORMAT
     * @return
     */
    public static String longToDate(long dateLong, String DATE_FORMAT) {
        return dateToStr(new Date(dateLong), DATE_FORMAT);
    }
    
    /**
     * convert a date to string in a specifies fromat.
     *
     * @param date
     * @param DATE_FORMAT
     * @return
     */
    public static String dateToStr(Date date, String DATE_FORMAT) {
        if (date == null) {
            return null;
        }
        SimpleDateFormat myFormat = new SimpleDateFormat(DATE_FORMAT);
        return myFormat.format(date);
    }

    /**
     * 获取两个日期的相差分钟数
     *
     * @param createTime 上次汇报时间
     * @param currentDate 当前时间
     * @return
     */
    public static Long compareDateMin(Date createTime, Date currentDate) {
        Long between = (currentDate.getTime() - createTime.getTime() );
        long min = between/(1000 * 60);//相差的分钟数
        return min;
    }

    /**
     * 时间戳转成Date(excel日期转换)
     * @param times
     * @return
     */
    public static Date conVerDate(Integer times) {
        if (times == 0){
            return new Date();
        } else {
            Calendar calendar = Calendar.getInstance();
            calendar.set(1900,Calendar.JANUARY,1);
            calendar.add(Calendar.DAY_OF_MONTH,times -2);
            Date date = calendar.getTime();
            return date;
        }

    }

    /**
     * 铸造判断领料时间
     * @param inputDate
     * @param
     * @return
     */
    public static Date adjustDateZhu(Date inputDate) {

        // 不同车间对应截止时间（小时 + 分钟）
        int cutoffHour = 7;
        int cutoffMinute = 0;

        // 转 LocalDateTime
        LocalDateTime now = inputDate.toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDateTime();

        // 当月 26 日的 cutoff 时间
        LocalDateTime cutoffTime = LocalDate.now()
                .withDayOfMonth(26)
                .atTime(cutoffHour, cutoffMinute);

        LocalDateTime result;

        // 如果当前时间超过 cutoffTime → 次月 1 号 00:00:00
        if (now.isAfter(cutoffTime)) {
            result = now.toLocalDate()
                    .plusMonths(1)
                    .withDayOfMonth(1)
                    .atStartOfDay();
        } else {
            // 未超过则保持不变
            result = now;
        }

        // 转 Date
        return Date.from(result.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 判断入库日期
     * @param inputDate
     * @param workshop
     * @return
     */
    public static Date adjustDateIntock(Date inputDate, String workshop) {

        // 不同车间对应截止时间（小时 + 分钟）
        int cutoffHour = 7;
        int cutoffMinute = 0;
        int dayOfMonth = 26;

        if (workshop.contains("机加")){
            dayOfMonth = 27;
            cutoffHour = 0;
        }

        // 转 LocalDateTime
        LocalDateTime now = inputDate.toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDateTime();

        // 当月 26 日的 cutoff 时间
        LocalDateTime cutoffTime = LocalDate.now()
                .withDayOfMonth(dayOfMonth)
                .atTime(cutoffHour, cutoffMinute);

        LocalDateTime result;

        // 如果当前时间超过 cutoffTime → 次月 1 号 00:00:00
        if (now.isAfter(cutoffTime)) {
            result = now.toLocalDate()
                    .plusMonths(1)
                    .withDayOfMonth(1)
                    .atStartOfDay();
        } else {
            // 未超过则保持不变
            result = now;
        }

        // 转 Date
        return Date.from(result.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 机加判断领料时间
     * @param inputDate
     * @return
     */
    public static Date adjustDateJiJia(Date inputDate) {

        LocalTime cutoff = LocalTime.of(7, 45);

        LocalDateTime now = inputDate.toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDateTime();

        LocalDate today = now.toLocalDate();
        int day = today.getDayOfMonth();
        LocalTime time = now.toLocalTime();

        LocalDate resultDate;

        // ====== ① 1号（无论时间是否 < 7:45，全算 1号） ======
        if (day == 1) {
            resultDate = today;
        }
        // ====== ② 27号及之后 → 次月1号 ======
        else if (day >= 27) {
            resultDate = today.plusMonths(1).withDayOfMonth(1);
        }
        // ====== ③ 26号逻辑 ======
        else if (day == 26) {
            if (time.isBefore(cutoff)) {
                resultDate = today; // 26号 7:45 前
            } else {
                resultDate = today.plusMonths(1).withDayOfMonth(1); // 26号 7:45 后
            }
        }
        // ====== ④ 2~25号逻辑 ======
        else {
            if (time.isBefore(cutoff)) {
                resultDate = today.minusDays(1); // 前一天
            } else {
                resultDate = today; // 当天
            }
        }

        return Date.from(resultDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
    }



    /**
     * 判断调拨日期
     * @param inputDate
     * @return
     */
    public static Date adjustDateTransfer(Date inputDate) {

        // 不同车间对应截止时间（小时 + 分钟）
        int cutoffHour = 0;
        int cutoffMinute = 0;
        int dayOfMonth = 26;

        // 转 LocalDateTime
        LocalDateTime now = inputDate.toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDateTime();

        // 当月 26 日的 cutoff 时间
        LocalDateTime cutoffTime = LocalDate.now()
                .withDayOfMonth(dayOfMonth)
                .atTime(cutoffHour, cutoffMinute);

        LocalDateTime result;

        // 如果当前时间超过 cutoffTime → 次月 1 号 00:00:00
        if (now.isAfter(cutoffTime)) {
            result = now.toLocalDate()
                    .plusMonths(1)
                    .withDayOfMonth(1)
                    .atStartOfDay();
        } else {
            // 未超过则保持不变
            result = now;
        }

        // 转 Date
        return Date.from(result.atZone(ZoneId.systemDefault()).toInstant());
    }

}
